package cc.md888.app.application.proxy.impl;

import cc.md888.app.application.proxy.ProxyInfoLookup;
import cc.md888.app.enums.ProxyProtocolEnum;
import cc.md888.app.exception.BizRuntimeException;
import cc.md888.app.infr.ip.IpInfoVO;
import cc.md888.app.infr.ip.convert.Ip123Convert;
import cc.md888.app.model.proxy.ProxyInfoCmd;
import cc.md888.result.ResultCode;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import springfox.documentation.spring.web.json.Json;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * 使用curl命令获取代理信息
 */
@Slf4j
public class OkHttpClientProxyInfoLookup implements ProxyInfoLookup {

    @Override
    public IpInfoVO lookup(ProxyInfoCmd cmd) {

        ProxyProtocolEnum proxyProtocolEnum = null;
        try{
            proxyProtocolEnum = ProxyProtocolEnum.valueOf(cmd.getProtocol());
        }catch (Exception e){
            throw BizRuntimeException.from(ResultCode.ERROR, "不支持的代理协议：" + cmd.getProtocol());
        }

        Proxy.Type proxtyType = null;
        switch (proxyProtocolEnum) {
            case HTTP:
                proxtyType = Proxy.Type.HTTP;
                break;
            case Socks5:
                proxtyType = Proxy.Type.SOCKS;
                break;
        }

        final OkHttpClient.Builder  builder = new OkHttpClient.Builder()
                .readTimeout(30, TimeUnit.SECONDS)
                .connectTimeout(30,TimeUnit.SECONDS)
                .proxy(new Proxy(
                        proxtyType,
                        InetSocketAddress.createUnresolved(cmd.getHost(), cmd.getPort())
                ));


        if(StringUtils.isNotEmpty(cmd.getUsername()) && StringUtils.isNotEmpty(cmd.getPassword())){
            builder.proxyAuthenticator(
                    new  Authenticator() {
                        @Override public Request authenticate(Route route, Response response) throws IOException {
                            String credential = Credentials.basic(cmd.getUsername(), cmd.getPassword());
                            return response.request().newBuilder()
                                    .header("Proxy-Authorization", credential)
                                    .build();
                        }
                    }
            );
        }

        String target = "https://www.ip123.in/ip.json";
        log.info("lookup proxy : {}", JSON.toJSONString(cmd));
        try {
            OkHttpClient client = builder.build();

            Request request = new Request.Builder()
                    .get()
                    .header("accept", "application/json")
                    .header("user-agent", "maodou/1.0")
                    .url(target)
                    .build();

            Response response = client.newCall(request).execute();
            log.info("lookup proxy: response code is {}",  response.code());
            if(!response.isSuccessful()){
                throw BizRuntimeException.from(ResultCode.ERROR, " response code is " + response.code());
            }

            ResponseBody responseBody = response.body();
            if(responseBody == null){
                log.info("lookup proxy: response body is empty");
                throw BizRuntimeException.from(ResultCode.ERROR, "response body is empty");
            }

            String body = responseBody.string();
            return new Ip123Convert().convert(body);
        } catch (Exception e) {
            log.error("lookup proxy error ", e);
            throw BizRuntimeException.from(ResultCode.ERROR, "获取代理信息失败，请稍后再试" );
        }
    }

    public static void main(String[] args) {
        ProxyInfoCmd cmd = new ProxyInfoCmd();
        cmd.setProtocol(ProxyProtocolEnum.Socks5.name());
        cmd.setHost("127.0.0.1");
        cmd.setPort(10808);
        IpInfoVO ipInfoVO = new OkHttpClientProxyInfoLookup().lookup(cmd);
        System.out.println(JSON.toJSONString(ipInfoVO));
    }

}
